unit Unit1;
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
interface

uses
{$IFNDEF FPC}
  Windows, XpMan,
{$ELSE}
  LCLType,
{$ENDIF}
  Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls, Menus, utils, tags, adaptors,
  adapt_consts, pl_consts, f_vises, trans_ru, plLst;

type
  { TPlMain }
  TPlMain = class(TForm)
    Panel1: TPanel;
    Label1: TLabel;
    path: TEdit;
    ADD: TButton;
    INFO: TButton;
    REMOVE: TButton;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    OPEN1: TMenuItem;
    OpenFolder1: TMenuItem;
    OpenPlaylist1: TMenuItem;
    SavePlaylist1: TMenuItem;
    View1: TMenuItem;
    Equalizer1: TMenuItem;
    Visualizations1: TMenuItem;
    OpenDialog1: TOpenDialog;
    Panel2: TPanel;
    playlist: TListBox;
    Timer1: TTimer;
    Pltm: TTimer;
    Panel3: TPanel;
    Splitter2: TSplitter;
    Panel4: TPanel;
    Trk: TScrollBar;
    Splitter1: TSplitter;
    Panel5: TPanel;
    Splitter3: TSplitter;
    bplay: TButton;
    bpause: TButton;
    bstop: TButton;
    volume: TTrackBar;
    rndchk: TCheckBox;
    rpt: TCheckBox;
    Button2: TButton;
    Button1: TButton;
    CLEAR: TButton;
    procedure FormCreate(Sender: TObject);
    procedure INFOClick(Sender: TObject);
    procedure playlistDblClick(Sender: TObject);
    procedure ADDClick(Sender: TObject);
    procedure REMOVEClick(Sender: TObject);
    procedure bstopClick(Sender: TObject);
    procedure bpauseClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Timer1Timer(Sender: TObject);
    procedure bplayClick(Sender: TObject);
    procedure volumeChange(Sender: TObject);
    procedure PltmTimer(Sender: TObject);
    procedure TrkScroll(Sender: TObject; ScrollCode: TScrollCode;
      var ScrollPos: Integer);
    procedure OPEN1Click(Sender: TObject);
    procedure SavePlaylist1Click(Sender: TObject);
    procedure playlistKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure Equalizer1Click(Sender: TObject);
    procedure OpenFolder1Click(Sender: TObject);
    procedure Visualizations1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure OpenPlaylist1Click(Sender: TObject);
    procedure CLEARClick(Sender: TObject);

  private
    slide: boolean;
    curlen: Int64;
    _tab: string;
    curlend: Double;
    played: boolean;

    procedure Play_Begin(const c_id: Cardinal);
    procedure Play_Disk(const num: longint);
    procedure Play_Stream (Name: string);
    procedure Stop_Stream;
    procedure Play_next;
    procedure Play_prev;
    { Private declarations }
  public
    paused: boolean;
    hstrm :DWORD;
    id: Longint;
    waveData: TWAVEDATA;
    FFTDATA: TFFTDATA;
    _fxs: array[0.. eq_maxcnt - 1] of DWORD;
    { Public declarations }
  end;
var
  PlMain: TPlMain;
implementation
uses Equalizer;
{$IFNDEF FPC}
{$R *.dfm}
{$ELSE}
{$R *.lfm}
{$ENDIF}

procedure TPlMain.OpenFolder1Click(Sender: TObject);
var
  fld_name: string;
begin
  fld_name := utils.Open_Folder();
  if (DirectoryExists(fld_name)) then
    plLst.Playlist_Add_FromFld(fld_name);
end;

procedure init;
begin
  l_size := 0;
  PlMain.id := 0;
  adaptors.ENGINE_INIT;
  adaptors.ENGINE_LOADALLPLUGINS;
end;

procedure TPlMain.Stop_Stream;
begin
  trk.Enabled := false;
  trk.Position := 0;
  adaptors.ENGINE_Terminate_Channel(hstrm);
end;

procedure TPlMain.Play_Disk(const num: longint);
begin
  //Bass_CdPlay(num, false, true);
end;

procedure TPlMain.Play_Begin(const c_id: CArdinal);
var
  i: Byte;
begin
  ENGINE_Terminate_Channel(hstrm);
  if ((id  < playlist.Count)and(id >= 0)) then
    playlist.Selected[id] := false;
  if (played) then
    Stop_stream;
  played := true;
  path.text := fl[c_id].file_path;
  if (not FileExists(path.Text)) then
  begin
    _error(_TEFILE_NOT_FOUND + ' ' + path.Text);
    path.Text := '';
    exit;
  end;
  hstrm := ENGINE_Create_channel(path.Text, false);
  if (hstrm = 0) then
  begin
    _error(_TE_STREAM_NOT_CREATED + ' ' + path.text);
    path.Text := '';
    exit;
  end;
  ENGINE_setattribute(hstrm, ENGINE_ATTRIB_VOL, volume.Position / 100);
  for i := 0 to eq_maxcnt - 1 do
    ENGINE_EQUALISER_INIT(hstrm, _fxs[i]);
    
  curlend := fl[c_id].length;
  label1.caption := '';
  //if (pl[c_id].title <> nil) then
    label1.caption := label1.caption + pl[c_id].title + ' ';
  //if (pl[c_id].album <> nil) then
    label1.caption := label1.caption + pl[c_id].album;
  //if (pl[c_id].artist <> nil) then
    label1.caption :=   label1.caption + ' by ' +  pl[c_id].artist;

  if (label1.Caption = '') then
    label1.Caption := fl[c_id].file_path;
  if (round(curlend) = 0) then
    curlend := adaptors.ENGINE_Get_Length(hstrm);
  Trk.Max := round(curlend);
  {Trk.position := 0;
  Trk.enabled := true;   }
  playlist.Selected[c_id] := true;
  pltm.Enabled := true;
  id := c_id;
end;

procedure TPlMain.Play_Stream(Name: string);
var
  f: pchar;
begin
  {f := pchar(name);
  hstrm := BASS_StreamCreateFile(FALSE, f, 0, 0, BASS_MP3_SETPOS);
  if (hstrm <> 0) then
    BASS_channelPlay(hstrm, false);        }
end;

procedure TPlMain.FormCreate(Sender: TObject);
begin
  init;
  Trk.enabled := true;
  played := true;
  paused := false;
  slide := false;
  id := 0;
end;

procedure TPlMain.INFOClick(Sender: TObject);
var
  i: longint;
begin
 for i := 0 to adaptors.plug_cnt - 1 do
 begin
  _error(plug_lst[i].pl_fname);
 end;
 for i := 0 to adaptors.media_names.Count - 1 do
  _error(media_names.Strings[i]);       
end;

procedure TPlMain.playlistDblClick(Sender: TObject);
begin
 Play_begin(playlist.ItemIndex)
end;

procedure TPlMain.ADDClick(Sender: TObject);
var
  pth: string;
begin
  pth := Open_File(filt_playable);
  if (FileExists(pth)) then
    PlayList_Add(pth);
end;

procedure TPlMain.REMOVEClick(Sender: TObject);
begin
  playlist_DeleteSelected;
end;

procedure TPlMain.bstopClick(Sender: TObject);
begin
    Stop_Stream;
end;

procedure TPlMain.bpauseClick(Sender: TObject);
begin
  if (played) then
  begin
    paused := true;
    ENGINE_Channel_Pause(hstrm);
  end
  else
    begin
      ENGINE_Channel_Play(hstrm, false);
      paused := false;
    end;
  played := not (played);
  pltm.Enabled := played;
end;

procedure TPlMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  STOP_stream;
  ENGINE_FREE;
end;

procedure TPlMain.Timer1Timer(Sender: TObject);
begin
  PlMain.Caption := 'CPU:  ' + FloatToStrF(ENgine_GETCPU, ffFixed, 4, 2) + '% time '+
  inttostr(Trk.position div 60) + ':' +inttostr(Trk.position mod 60)  + '//' + inttostr(trk.Max div 60)+ ':' +inttostr(Trk.max mod 60);
end;

procedure TPlMain.bplayClick(Sender: TObject);
begin
  if (paused) then
  begin
    ENGINE_Channel_Play(hstrm, false);
    paused := not(paused);
  end
  else
    if (id > (playlist.Count - 1)) then exit;
      Play_begin(id);
end;

procedure TPlMain.volumeChange(Sender: TObject);
begin
   ENGINE_setattribute(hstrm, ENGINE_ATTRIB_VOL, volume.Position / 100);
end;

procedure TplMain.play_next;
var
  nid: Longint;
begin
  Stop_Stream;
  nid := id;
  trk.Position := 0;
  if (rndchk.checked) then
     nid := random(PlayList.count)
  else
    if (rpt.checked) then nid := (nid + 1) mod PlayList.count
    else
        if (nid = (PlayList.Count - 1)) then
          plTm.enabled := false
        else
          nid := nid + 1;

  if (plTm.enabled) then
     Play_begin(nid);
end;

procedure TplMain.Play_prev;
var
  nid: Longint;
begin
  Stop_Stream;
  nid := id;
  trk.Position := 0;
  if (rndchk.checked) then
     nid := random(PlayList.count)
  else
    if (rpt.checked) then nid := (nid - 1 + PlayList.count) mod PlayList.count
    else
        if (nid = 0) then
          plTm.enabled := false
        else
          nid := nid - 1;

  if (plTm.enabled) then
     Play_begin(nid);
end;

procedure TPlMain.PltmTimer(Sender: TObject);
begin
  if (slide) then exit;
  if (Trk.Position < Trk.Max) then
  begin
    Trk.Position := round(ENGINE_Channel_Bytes2Seconds(hstrm, ENGINE_Cannel_GETPOSITION(hstrm, ENGINE_POS_BYTE)));
    Trk.enabled := true;
    ENGINE_Channel_GETDATA(hstrm, @WAVEDATA, WAVE_LEN);
    ENGINE_Channel_GETDATA(hstrm, @FFTDATA, ENGINE_FFT_DATA_1024)
  end
  else
  begin
    play_next;
    sleep(200);
  end;
end;

procedure TPlMain.TrkScroll(Sender: TObject; ScrollCode: TScrollCode;
  var ScrollPos: Integer);
var
  curpos: Int64;
begin
  {case ScrollCode of
       scLineUp: PlMain.caption := 'SCLineUp';
       scLineDown: PlMain.caption := 'SCLineDown';
       scPageUp: PlMain.caption := 'scPageUp';
       scPageDown: PlMain.caption := 'scPageDown';
       scPosition: PlMain.caption := 'scPosition';
       scTrack: PlMain.caption := 'scTrack';
       scTop: PlMain.caption := 'scTop';
       scBottom: PlMain.caption := 'scBottom';
       scEndScroll: PlMain.caption := 'scEndScroll';
  end;       }
  slide := (ScrollCode <> scEndScroll);
  if (not slide) then
  begin
    curpos := ENGINE_Channel_SECONDS2BYTES(hstrm, scrollpos);
    engine_channel_SetPosition(hstrm, curpos, ENGINE_POS_BYTE);
    slide := false;
  end;
end;

procedure TPlMain.OPEN1Click(Sender: TObject);
var
  files : PstringList;
  l_file: TstringList;
  dest: string;
  i: Byte;
begin
  files := Open_Mfile(filt_playable);
  if (files = nil) then exit;
  l_file := files^;
  if ((l_file.Count = 1)and(Str_ToLow(l_file.Strings[0]) = 'zip')) then
  begin
    dest := GetTmpDir;
    utils.Unzip(l_file.Strings[0], dest);
    Playlist_Add_FromFld(dest);
    files^.FreeInstance;
  end
  else
    PlayList_Load_FromStringLst(l_file);

end;

procedure TPlMain.SavePlaylist1Click(Sender: TObject);
var
  pl: TstringList;
  i : Cardinal;
begin
  if (playlist.Count = 0) then exit;
  pl := TstringList.Create;
  for i := 0 to playlist.Count - 1 do
    pl.Append(fl[i].file_path);
  Save_File(pl, filt_playlist);
  pl.FreeInstance;
end;

procedure TPlMain.playlistKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
  i: Longint;
begin
  case key of
    46: PlayList_DeleteSelected;
  end;
end;

procedure TPlMain.OpenPlaylist1Click(Sender: TObject);
begin
  PlayList_Load_From_Playlist(Open_File(filt_playlist));
end;

procedure TPlMain.Equalizer1Click(Sender: TObject);
begin
  Eq.show;
end;

procedure TPlMain.Visualizations1Click(Sender: TObject);
begin
  pl_vises.SHow;
end;

procedure TPlMain.Button1Click(Sender: TObject);
begin
   Play_next;
end;

procedure TPlMain.Button2Click(Sender: TObject);
begin
  play_prev;
end;

procedure TPlMain.CLEARClick(Sender: TObject);
begin
  PlayList_clear;
end;

end.